home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / Virtual User 1.0b5 / Example Scripts / TowersOfHanoi.vu < prev   
Encoding:
Text File  |  1990-10-05  |  8.6 KB  |  259 lines  |  [TEXT/MPS ]

  1. #
  2. #    File:        TowersOfHanoi.vu
  3. #
  4. #    Contains:    The script solves the problem of 'Towers of Hanoi' using Finder windows
  5. #                as 'towers'.
  6. #
  7. #                To be able to run this script, the target should be in
  8. #                Finder, with either a window open or a volume selected.
  9. #                Also, set the following variables towards the end of this file:
  10. #                (Default values are in parens)
  11. #                Total_disks(3)    : the number of disks you want the towers to be built with.
  12. #                From_tower(1)    : the tower from which you want to move;
  13. #                To_tower(3)        : the tower to which you want to move;
  14. #                Using_tower(2)    : the tower which will be used as a temporary one;
  15. #                System7(false)    : whether or not you're running System 7
  16. #
  17. #    Conventions:    Global variables begin with a capital letter
  18. #
  19. #    Warning:    This script will create a set of folders in the open/selected volume.
  20. #                So do trash these folders after the script completes its execution.
  21. #                Also, if the folders with the names used already exist (from previous execution)
  22. #                the script will not work.
  23. #
  24. #    Written by:    P Nagarajan
  25. #
  26. #    Copyright:    © 1990 by Apple Computer, Inc., all rights reserved.
  27. #
  28. #    Change History:
  29. #
  30. #        5/17/90        JAS        A few formatting changes
  31. #
  32. #        3/29/89           naga    Creation
  33. #                             
  34. #
  35. #    To Do:
  36. #
  37.  
  38.  
  39. # ********************************************************************************************
  40. task insert_into_list(element, position, lst)
  41. # This task inserts/replaces an 'element' at 'position' in a list contained
  42. # in the argument 'lst', and returns the new list.
  43. # 'position' must be  an Integer.
  44. # Prerequisites:: Presence of a list in 'lst'.
  45. begin
  46.     local_list := {};
  47.     for pos := 1 to (position - 1) do 
  48.         local_list := local_list + {lst[pos]};
  49.     local_list := local_list + {element};
  50.     size_of_list := card(lst);
  51.     for pos := (position + 1) to size_of_list do 
  52.         local_list := local_list + {lst[pos]};
  53.     return local_list;
  54. end; #task insert_into_list
  55.  
  56.  
  57.  
  58. # ********************************************************************************************
  59. task add_move(from_t, to_t, all_moves)
  60. # Adds a move of the form {from_t, to_t} to the global list 'all_moves'.
  61. # All Arguments should be integers
  62. begin
  63.     all_moves := all_moves + {{from_t, to_t}};
  64.     return all_moves;
  65. end;
  66.  
  67.  
  68. # ********************************************************************************************
  69. task gen_moves(from_t, to_t, using, num_disks, all_moves)
  70. # Generates moves for moving 'num_disks' number of disks from 'from_t' tower
  71. # to 'to_t' tower using 'using' tower
  72. # All Arguments should be integers
  73. begin
  74.     if not (num_disks = 0) do
  75.     begin
  76.         if (num_disks = 1) do
  77.             return add_move(from_t, to_t, all_moves);
  78.         else do
  79.         begin
  80.             all_moves := gen_moves(from_t, using, to_t, num_disks - 1, all_moves);
  81.             all_moves := add_move(from_t, to_t, all_moves);
  82.             all_moves := gen_moves(using, to_t, from_t, num_disks - 1, all_moves);
  83.             return all_moves;
  84.         end;
  85.     end;
  86. end; #task gen_moves
  87.  
  88.  
  89. # ********************************************************************************************
  90. task set_up_tower(tower, no_of_disks)
  91. # Sets up the tower called Tower{tower} made of 'no_of_disks'
  92. # Prereqs::  'Base_dimension' : an integer specifying the size of the base disk(window)
  93. #             'Position_of_tower' : a list having the initial position of each tower,
  94. #                                  position being {x, y}.
  95. # Results:: 'Delta_for_tower' : sets up this global list, which gives the displacement of the topmost
  96. #                               disk from the base, on each tower. ( a list of 3 integers).
  97. #            'success' : if setup successful returns true else false.
  98. begin
  99.     global Screen_rect;
  100.     global Base_dimension;
  101.     global Position_of_tower;
  102.     
  103.     j := tower; #tower number
  104.     i := no_of_disks;
  105.     all_windows := collect[window];
  106.     if (card(all_windows) = 1) do
  107.     begin
  108.         Drag [Window] a: {Screen_rect[3]-12, Screen_rect[4]-50};
  109.         Select [MenuItem t: 'New Folder' m:'File'];
  110.         Type k:{"Tower{j}"};
  111.         Select [MenuItem t:'Open' m:'File'];
  112.         Drag [Window t:"Tower{j}"] a: {1,20};
  113.         Size [Window t:"Tower{j}"] h: Base_dimension w:Base_dimension;
  114.         Drag [Window t:"Tower{j}"] a: {Screen_rect[3]-12, Screen_rect[4]-50};
  115.         global Delta_for_tower := {0,0,0};
  116.         delta_move := Delta_for_tower[j];
  117.         while (i > 0) do
  118.         begin
  119.             Select [Window t:"Tower{j}"];
  120.             Select [MenuItem t: 'New Folder' m:'File'];
  121.             Type k:{"Disk{i}"};
  122.             Select [MenuItem t:'Open' m:'File'];
  123.             new_position := {(Position_of_tower[j][1] + delta_move),
  124.                              (Position_of_tower[j][2] - delta_move) };
  125.             Drag [Window t:"Disk{i}"] a: {1,20};
  126.             Size [Window t:"Disk{i}"] h:Base_dimension - delta_move/2 w:Base_dimension - 2*delta_move;
  127.             Drag [Window t:"Disk{i}"] a: new_position;
  128.             delta_move := delta_move + 5;
  129.             i := i - 1;
  130.         end;
  131.         Delta_for_tower := insert_into_list((delta_move - 5), j, Delta_for_tower);
  132.         success := true;
  133.     end; #if one open window exists
  134.     else do #try to open a single window
  135.     begin
  136.         if (card(all_windows) > 1) do
  137.             for each w in all_windows do 
  138.                 if w.c close[window];
  139.         all_windows := collect[window];
  140.         if (card(all_windows) = 0) or (global System7) do
  141.         begin
  142.             if (match [menuItem t:'Open' m:'File' e:true]!) do
  143.             begin
  144.                 select [menuItem t:'Open' m:'File']!;
  145.                 success := set_up_tower(tower, no_of_disks);
  146.             end; #if a window can be opened thru' the menu
  147.             else do
  148.                 success := false;
  149.         end; #no windows currently
  150.         else do #could not close all windows
  151.             success := false;
  152.     end; #opened a single window
  153.     return success;
  154. end; #task set_up_tower
  155.  
  156.  
  157. # ********************************************************************************************
  158. task make_moves(all_moves)
  159. #this task actually makes the moves (dragging windows) using the moves,
  160. #stored in the argument 'all_moves'.
  161. #Prereqs :: 'all_moves' a list containing moves of form {i,j}
  162. #            'Position_of_tower' : a list having the initial position of each tower,
  163. #                                  position being {x, y}.
  164. #            'Delta_for_tower' : a list which gives the displacement for the next disk 
  165. #                                to be placed on a tower (from the original position of the tower).
  166. begin
  167.     global Delta_for_tower;
  168.     global Position_of_tower;
  169.     
  170.     x := 1; #index to get x-coord
  171.     y := 2; #index to get y-coord
  172.     for each disk_move in all_moves do 
  173.     begin 
  174.         i := disk_move[1] ;
  175.         j := disk_move[2] ; #move from tower i to tower j
  176.         delta_move := Delta_for_tower[j] + 5;
  177.         newx := Position_of_tower[j][x] + delta_move;
  178.         newy := Position_of_tower[j][y] - delta_move;
  179.         new_position := {newx, newy};
  180.         wind_rect := {Position_of_tower[i][x] + Delta_for_tower[i], #left
  181.                       Position_of_tower[i][y] - Delta_for_tower[i], #top
  182.                       0 ,#right
  183.                       0 #bottom
  184.                       };
  185.         Select [Window r:?rect1:wind_rect];
  186.         Drag [Window] a: new_position;
  187.         Delta_for_tower := update_Delta_for_tower(delta_move, i, j, Delta_for_tower);
  188.     end; #for_each move
  189. end; #task make_moves
  190.  
  191.  
  192. # ********************************************************************************************
  193. task update_Delta_for_tower(delta_move, from_t, to_t, Delta_for_tower)
  194. begin
  195.     if (Delta_for_tower[from_t] <> 0) do
  196.         Delta_for_tower := insert_into_list((Delta_for_tower[from_t] - 5), from_t, Delta_for_tower);
  197.     Delta_for_tower := insert_into_list(delta_move, to_t, Delta_for_tower);
  198.     return Delta_for_tower;
  199. end; #task update_Delta_for_tower
  200.  
  201.  
  202.  
  203. #####   EXECUTION STARTS HERE  ######
  204.  
  205. Total_disks := 3;
  206. From_tower     := 1;
  207. To_tower     := 3;
  208. Using_tower := 2;
  209. System7     := false;
  210.  
  211. All_moves     := {};
  212.  
  213. if (System7) Patience(2);
  214.  
  215. match[screen r:?Screen_rect m:true];
  216. screen_width := Screen_rect[3]- Screen_rect[1];
  217. screen_height := Screen_rect[4]- Screen_rect[2];
  218. Max_disks1 := ((Screen_height - 20) - 112)/5;
  219. Max_disks2 := (((Screen_width - 30)/3) - 112)/5;
  220. if Max_disks2 >= Max_disks1 #find the tighter of the two bounds
  221. begin
  222.     Max_disks := Max_disks1;
  223. end;#if
  224. else
  225. begin
  226.     Max_disks := Max_disks2;
  227. end;#if
  228. if Total_disks > Max_disks
  229. begin
  230.     println "Sorry can draw only tower with a maximum of ", Max_disks,
  231.           " disks on this target's main screen.";
  232.     println "Try with lesser number of disks or a larger screen!";
  233. end;#if
  234. else
  235. begin
  236.     Base_dimension := 117 + 5*(Total_disks - 1);
  237.     X_offset := (Screen_width-Base_dimension*3)/4;
  238.     Y_offset := (Screen_height-Base_dimension)/2;
  239.     Position_of_tower := {{(Screen_rect[1] + X_offset),(Screen_rect[2] + Y_offset)},
  240.                           {(Screen_rect[1] + X_offset*2 + Base_dimension), (Screen_rect[2] + Y_offset)},
  241.                           {(Screen_rect[1] + X_offset*3 + Base_dimension*2), (Screen_rect[2] + Y_offset)}};
  242.  
  243.     println "Now computing the moves...";
  244.     All_moves := gen_moves(From_tower, To_tower, Using_tower, Total_disks, All_moves);
  245.     println "done!";
  246.     println "Now setting up the tower of disks...";
  247.     Success := set_up_tower(From_tower, Total_disks); 
  248.     if (Success) do 
  249.     begin
  250.         println "done!";
  251.         println "Now making the moves...";
  252.         make_moves(All_moves);
  253.         println "done!";
  254.     end;
  255.     else do
  256.         println "Target not set up to solve the problem. Sorry."; 
  257. end;#else Total_disks permissible
  258.  
  259.